bitkeeper revision 1.1159.99.4 (41626f06VquclgVVpIeHy9z2K3jW-A)
authorkaf24@freefall.cl.cam.ac.uk <kaf24@freefall.cl.cam.ac.uk>
Tue, 5 Oct 2004 09:53:10 +0000 (09:53 +0000)
committerkaf24@freefall.cl.cam.ac.uk <kaf24@freefall.cl.cam.ac.uk>
Tue, 5 Oct 2004 09:53:10 +0000 (09:53 +0000)
Rationalise scheduler locking. A bit more conservative now, but much
simpler! I only applied this to the basic BVT scheduler -- the others
are still unsafe and have been removed from the basic build.

xen/common/Makefile
xen/common/domain.c
xen/common/sched_bvt.c
xen/common/schedule.c
xen/include/xen/sched.h

index 84e3a1292f9251788fc29bf313de29e8e8c0df3d..d934a2e040685ee720dfb5ee1955077f675b4f55 100644 (file)
@@ -19,6 +19,14 @@ ifneq ($(trace),y)
 OBJS := $(subst trace.o,,$(OBJS))
 endif
 
+ifneq ($(broken_schedulers),y)
+OBJS := $(subst sched_atropos.o,,$(OBJS))
+OBJS := $(subst sched_fair_bvt.o,,$(OBJS))
+OBJS := $(subst sched_rrobin.o,,$(OBJS))
+else
+CFLAGS += -DBROKEN_SCHEDULERS
+endif
+
 default: $(OBJS)
        $(LD) $(LDFLAGS) -r -o common.o $(OBJS)
 
index b4b719d4197ada420b64801ba64980e0beca2c8f..d7509bc9764a34aaadc73765c5a7fd478fdc73b0 100644 (file)
@@ -39,7 +39,6 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
     d->domain    = dom_id;
     d->processor = cpu;
     d->create_time = NOW();
-    spin_lock_init(&d->sleep_lock);
  
     memcpy(&d->thread, &idle0_task.thread, sizeof(d->thread));
 
index c526f9fc9acc979a90f7b079f9e15efb6eaba2ad..46e374a2c446e295e4a93c3eac35f88880e8dbdf 100644 (file)
@@ -37,7 +37,7 @@ struct bvt_dom_info
     u32                 evt;              /* effective virtual time */
     int                 warpback;         /* warp?  */
     int                 warp;             /* warp set and within the warp 
-                                                                     limits*/
+                                             limits*/
     s32                 warp_value;       /* virtual time warp */
     s_time_t            warpl;            /* warp limit */
     struct ac_timer     warp_timer;       /* deals with warpl */
@@ -47,12 +47,10 @@ struct bvt_dom_info
 
 struct bvt_cpu_info
 {
-    spinlock_t          run_lock;   /* protects runqueue */
-    struct list_head    runqueue;   /* runqueue for given processor */ 
-    unsigned long       svt;        /* XXX check this is unsigned long! */
+    struct list_head    runqueue;
+    unsigned long       svt;
 };
 
-
 #define BVT_INFO(p)   ((struct bvt_dom_info *)(p)->sched_priv)
 #define CPU_INFO(cpu) ((struct bvt_cpu_info *)(schedule_data[cpu]).sched_priv)
 #define RUNLIST(p)    ((struct list_head *)&(BVT_INFO(p)->run_list))
@@ -64,13 +62,8 @@ struct bvt_cpu_info
 #define TIME_SLOP      (s32)MICROSECS(50)     /* allow time to slip a bit */
 static s32 ctx_allow = (s32)MILLISECS(5);     /* context switch allowance */
 
-/* SLAB cache for struct bvt_dom_info objects */
 static xmem_cache_t *dom_info_cache;
 
-/*
- * Wrappers for run-queue management. Must be called with the run_lock
- * held.
- */
 static inline void __add_to_runqueue_head(struct domain *d)
 {
     list_add(RUNLIST(d), RUNQUEUE(d->processor));
@@ -98,43 +91,42 @@ static inline int __task_on_runqueue(struct domain *d)
 static void warp_timer_fn(unsigned long pointer)
 {
     struct bvt_dom_info *inf = (struct bvt_dom_info *)pointer;
-    unsigned long flags; 
+    unsigned int cpu = inf->domain->processor;
     
-    spin_lock_irqsave(&CPU_INFO(inf->domain->processor)->run_lock, flags);
+    spin_lock_irq(&schedule_data[cpu].schedule_lock);
+
     inf->warp = 0;
+
     /* unwarp equal to zero => stop warping */
-    if(inf->warpu == 0)
+    if ( inf->warpu == 0 )
     {
         inf->warpback = 0;
-        goto reschedule;
+        cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);   
     }
     
     /* set unwarp timer */
     inf->unwarp_timer.expires = NOW() + inf->warpu;
     add_ac_timer(&inf->unwarp_timer);
-    spin_unlock_irqrestore(&CPU_INFO(inf->domain->processor)->run_lock, flags);
 
-reschedule:
-    cpu_raise_softirq(inf->domain->processor, SCHEDULE_SOFTIRQ);   
+    spin_unlock_irq(&schedule_data[cpu].schedule_lock);
 }
 
 static void unwarp_timer_fn(unsigned long pointer)
 {
-     struct bvt_dom_info *inf = (struct bvt_dom_info *)pointer;
-     unsigned long flags;
+    struct bvt_dom_info *inf = (struct bvt_dom_info *)pointer;
+    unsigned int cpu = inf->domain->processor;
+
+    spin_lock_irq(&schedule_data[cpu].schedule_lock);
 
-     spin_lock_irqsave(&CPU_INFO(inf->domain->processor)->run_lock, flags);
-    if(inf->warpback)
+    if ( inf->warpback )
     {
         inf->warp = 1;
-        cpu_raise_softirq(inf->domain->processor, SCHEDULE_SOFTIRQ);   
+        cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);   
     }
-    
-    spin_unlock_irqrestore(&CPU_INFO(inf->domain->processor)->run_lock, flags);
+     
+    spin_unlock_irq(&schedule_data[cpu].schedule_lock);
 }
 
-
-
 static inline u32 calc_avt(struct domain *d, s_time_t now)
 {
     u32 ranfor, mcus;
@@ -146,15 +138,14 @@ static inline u32 calc_avt(struct domain *d, s_time_t now)
     return inf->avt + mcus * inf->mcu_advance;
 }
 
-
 /*
  * Calculate the effective virtual time for a domain. Take into account 
  * warping limits
  */
 static inline u32 calc_evt(struct domain *d, u32 avt)
 {
-   struct bvt_dom_info *inf = BVT_INFO(d);
-   /* TODO The warp routines need to be rewritten GM */
+    struct bvt_dom_info *inf = BVT_INFO(d);
+    /* TODO The warp routines need to be rewritten GM */
  
     if ( inf->warp ) 
         return avt - inf->warp_value;
@@ -168,26 +159,25 @@ static inline u32 calc_evt(struct domain *d, u32 avt)
  *
  * Returns non-zero on failure.
  */
-int bvt_alloc_task(struct domain *p)
+int bvt_alloc_task(struct domain *d)
 {
-    p->sched_priv = xmem_cache_alloc(dom_info_cache);
-    if ( p->sched_priv == NULL )
+    if ( (d->sched_priv = xmem_cache_alloc(dom_info_cache)) == NULL )
         return -1;
-    
+    memset(d->sched_priv, 0, sizeof(struct bvt_dom_info));
     return 0;
 }
 
 /*
  * Add and remove a domain
  */
-void bvt_add_task(struct domain *p
+void bvt_add_task(struct domain *d
 {
-    struct bvt_dom_info *inf = BVT_INFO(p);
+    struct bvt_dom_info *inf = BVT_INFO(d);
     ASSERT(inf != NULL);
-    ASSERT(p   != NULL);
+    ASSERT(d   != NULL);
 
     inf->mcu_advance = MCU_ADVANCE;
-    inf->domain = p;
+    inf->domain      = d;
     inf->warpback    = 0;
     /* Set some default values here. */
     inf->warp        = 0;
@@ -196,135 +186,95 @@ void bvt_add_task(struct domain *p)
     inf->warpu       = MILLISECS(1000);
     /* initialise the timers */
     init_ac_timer(&inf->warp_timer);
-    inf->warp_timer.cpu = p->processor;
+    inf->warp_timer.cpu = d->processor;
     inf->warp_timer.data = (unsigned long)inf;
     inf->warp_timer.function = &warp_timer_fn;
     init_ac_timer(&inf->unwarp_timer);
-    inf->unwarp_timer.cpu = p->processor;
+    inf->unwarp_timer.cpu = d->processor;
     inf->unwarp_timer.data = (unsigned long)inf;
     inf->unwarp_timer.function = &unwarp_timer_fn;
     
-    if ( p->domain == IDLE_DOMAIN_ID )
+    if ( d->domain == IDLE_DOMAIN_ID )
     {
         inf->avt = inf->evt = ~0U;
     } 
     else 
     {
         /* Set avt and evt to system virtual time. */
-        inf->avt         = CPU_SVT(p->processor);
-        inf->evt         = CPU_SVT(p->processor);
-   }
-
-    return;
+        inf->avt = CPU_SVT(d->processor);
+        inf->evt = CPU_SVT(d->processor);
+    }
 }
 
 int bvt_init_idle_task(struct domain *p)
 {
-    unsigned long flags;
-
-    if(bvt_alloc_task(p) < 0) return -1;
+    if ( bvt_alloc_task(p) < 0 )
+        return -1;
 
     bvt_add_task(p);
 
-    spin_lock_irqsave(&CPU_INFO(p->processor)->run_lock, flags);
-    
     set_bit(DF_RUNNING, &p->flags);
     if ( !__task_on_runqueue(p) )
         __add_to_runqueue_head(p);
         
-    spin_unlock_irqrestore(&CPU_INFO(p->processor)->run_lock, flags);
-
     return 0;
 }
 
 void bvt_wake(struct domain *d)
 {
-    unsigned long       flags;
     struct bvt_dom_info *inf = BVT_INFO(d);
     struct domain       *curr;
     s_time_t            now, r_time;
     int                 cpu = d->processor;
     u32                 curr_evt;
 
-    /* The runqueue accesses must be protected */
-    spin_lock_irqsave(&CPU_INFO(cpu)->run_lock, flags);
-    
-    /* If on the runqueue already then someone has done the wakeup work. */
     if ( unlikely(__task_on_runqueue(d)) )
-    {
-        spin_unlock_irqrestore(&CPU_INFO(cpu)->run_lock, flags);
         return;
-    }
 
     __add_to_runqueue_head(d);
 
     now = NOW();
 
     /* Set the BVT parameters. AVT should always be updated 
-        if CPU migration ocurred.*/
+       if CPU migration ocurred.*/
     if ( inf->avt < CPU_SVT(cpu) || 
-            unlikely(test_bit(DF_MIGRATED, &d->flags)) )
+         unlikely(test_bit(DF_MIGRATED, &d->flags)) )
         inf->avt = CPU_SVT(cpu);
 
     /* Deal with warping here. */
     inf->evt = calc_evt(d, inf->avt);
-    spin_unlock_irqrestore(&CPU_INFO(cpu)->run_lock, flags);
-    
-    /* Access to schedule_data protected by schedule_lock */
-    spin_lock_irqsave(&schedule_data[cpu].schedule_lock, flags);
     
     curr = schedule_data[cpu].curr;
     curr_evt = calc_evt(curr, calc_avt(curr, now));
     /* Calculate the time the current domain would run assuming
        the second smallest evt is of the newly woken domain */
     r_time = curr->lastschd +
-             ((inf->evt - curr_evt) / BVT_INFO(curr)->mcu_advance) +
-             ctx_allow;
+        ((inf->evt - curr_evt) / BVT_INFO(curr)->mcu_advance) +
+        ctx_allow;
 
     if ( is_idle_task(curr) || (inf->evt <= curr_evt) )
         cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
     else if ( schedule_data[cpu].s_timer.expires > r_time )
         mod_ac_timer(&schedule_data[cpu].s_timer, r_time);
-
-    spin_unlock_irqrestore(&schedule_data[cpu].schedule_lock, flags);  
 }
 
 
 static void bvt_sleep(struct domain *d)
 {
-    unsigned long flags;
-    
     if ( test_bit(DF_RUNNING, &d->flags) )
         cpu_raise_softirq(d->processor, SCHEDULE_SOFTIRQ);
-    else 
-    {
-        /* The runqueue accesses must be protected */
-        spin_lock_irqsave(&CPU_INFO(d->processor)->run_lock, flags);
-        
-        
-        if ( __task_on_runqueue(d) )
-            __del_from_runqueue(d);
-
-        spin_unlock_irqrestore(&CPU_INFO(d->processor)->run_lock, flags);    
-    }
+    else  if ( __task_on_runqueue(d) )
+        __del_from_runqueue(d);
 }
 
 /**
  * bvt_free_task - free BVT private structures for a task
- * @p:             task
+ * @d:             task
  */
-void bvt_free_task(struct domain *p)
-{
-    ASSERT( p->sched_priv != NULL );
-    xmem_cache_free( dom_info_cache, p->sched_priv );
-}
-
-
-/* 
- * Block the currently-executing domain until a pertinent event occurs.
- */
-static void bvt_do_block(struct domain *p)
+void bvt_free_task(struct domain *d)
 {
+    ASSERT(d->sched_priv != NULL);
+    xmem_cache_free(dom_info_cache, d->sched_priv);
 }
 
 /* Control the scheduler. */
@@ -333,24 +283,19 @@ int bvt_ctl(struct sched_ctl_cmd *cmd)
     struct bvt_ctl *params = &cmd->u.bvt;
 
     if ( cmd->direction == SCHED_INFO_PUT )
-    { 
         ctx_allow = params->ctx_allow;
-    }
     else
-    {
         params->ctx_allow = ctx_allow;
-    }
     
     return 0;
 }
 
 /* Adjust scheduling parameter for a given domain. */
-int bvt_adjdom(struct domain *p,
-               struct sched_adjdom_cmd *cmd)
+int bvt_adjdom(
+    struct domain *d, struct sched_adjdom_cmd *cmd)
 {
     struct bvt_adjdom *params = &cmd->u.bvt;
-    unsigned long flags;
-
+    
     if ( cmd->direction == SCHED_INFO_PUT )
     {
         u32 mcu_adv = params->mcu_adv;
@@ -359,27 +304,17 @@ int bvt_adjdom(struct domain *p,
         s_time_t warpl = params->warpl;
         s_time_t warpu = params->warpu;
         
-        struct bvt_dom_info *inf = BVT_INFO(p);
+        struct bvt_dom_info *inf = BVT_INFO(d);
         
         DPRINTK("Get domain %u bvt mcu_adv=%u, warpback=%d, warpvalue=%d, "
                 "warpl=%lld, warpu=%lld\n",
-                p->domain, inf->mcu_advance, inf->warpback, inf->warp_value,
+                d->domain, inf->mcu_advance, inf->warpback, inf->warp_value,
                 inf->warpl, inf->warpu);
 
         /* Sanity -- this can avoid divide-by-zero. */
-        if ( mcu_adv == 0 )
-        {
-            printk("Mcu advance must not be set to 0 (domain %d)\n",p->domain);
+        if ( (mcu_adv == 0) || (warpl < 0) || (warpu < 0) )
             return -EINVAL;
-        }
-        else if ( warpl < 0 || warpu < 0)
-        {
-            printk("Warp limits must be >= 0 (domain %d)\n", p->domain);
-            return -EINVAL;
-        }
-        
-        
-        spin_lock_irqsave(&CPU_INFO(p->processor)->run_lock, flags);   
+
         inf->mcu_advance = mcu_adv;
         inf->warpback = warpback;  
         /* The warp should be the same as warpback */
@@ -391,27 +326,23 @@ int bvt_adjdom(struct domain *p,
         /* If the unwarp timer set up it needs to be removed */
         rem_ac_timer(&inf->unwarp_timer);
         /* If we stop warping the warp timer needs to be removed */
-        if(!warpback)
+        if ( !warpback )
             rem_ac_timer(&inf->warp_timer);
         
         DPRINTK("Get domain %u bvt mcu_adv=%u, warpback=%d, warpvalue=%d, "
                 "warpl=%lld, warpu=%lld\n",
-                p->domain, inf->mcu_advance, inf->warpback, inf->warp_value,
+                d->domain, inf->mcu_advance, inf->warpback, inf->warp_value,
                 inf->warpl, inf->warpu);
                 
-        spin_unlock_irqrestore(&CPU_INFO(p->processor)->run_lock, flags);
     }
     else if ( cmd->direction == SCHED_INFO_GET )
     {
-        struct bvt_dom_info *inf = BVT_INFO(p);
-
-        spin_lock_irqsave(&CPU_INFO(p->processor)->run_lock, flags);   
+        struct bvt_dom_info *inf = BVT_INFO(d);
         params->mcu_adv     = inf->mcu_advance;
         params->warpvalue   = inf->warp_value;
         params->warpback    = inf->warpback;
         params->warpl       = inf->warpl;
         params->warpu       = inf->warpu;
-        spin_unlock_irqrestore(&CPU_INFO(p->processor)->run_lock, flags);
     }
     
     return 0;
@@ -427,23 +358,19 @@ int bvt_adjdom(struct domain *p,
  */
 static task_slice_t bvt_do_schedule(s_time_t now)
 {
-    unsigned long flags;
-    struct domain *prev = current, *next = NULL, *next_prime, *p; 
+    struct domain      *prev = current, *next = NULL, *next_prime, *p; 
     struct list_head   *tmp;
     int                 cpu = prev->processor;
     s32                 r_time;     /* time for new dom to run */
     u32                 next_evt, next_prime_evt, min_avt;
-    struct bvt_dom_info *prev_inf       = BVT_INFO(prev),
-                        *p_inf          = NULL,
-                        *next_inf       = NULL,
-                        *next_prime_inf = NULL;
+    struct bvt_dom_info *prev_inf       = BVT_INFO(prev);
+    struct bvt_dom_info *p_inf          = NULL;
+    struct bvt_dom_info *next_inf       = NULL;
+    struct bvt_dom_info *next_prime_inf = NULL;
     task_slice_t        ret;
 
-
     ASSERT(prev->sched_priv != NULL);
     ASSERT(prev_inf != NULL);
-    spin_lock_irqsave(&CPU_INFO(cpu)->run_lock, flags);
-
     ASSERT(__task_on_runqueue(prev));
 
     if ( likely(!is_idle_task(prev)) ) 
@@ -511,8 +438,6 @@ static task_slice_t bvt_do_schedule(s_time_t now)
         add_ac_timer(&next_inf->warp_timer);
     }
    
-    spin_unlock_irqrestore(&CPU_INFO(cpu)->run_lock, flags);
     /* Extract the domain pointers from the dom infos */
     next        = next_inf->domain;
     next_prime  = next_prime_inf->domain;
@@ -524,9 +449,9 @@ static task_slice_t bvt_do_schedule(s_time_t now)
     /* check for virtual time overrun on this cpu */
     if ( CPU_SVT(cpu) >= 0xf0000000 )
     {
-        u_long t_flags;
-        
-        write_lock_irqsave(&tasklist_lock, t_flags); 
+        ASSERT(!local_irq_is_enabled());
+
+        write_lock(&tasklist_lock);
         
         for_each_domain ( p )
         {
@@ -538,7 +463,7 @@ static task_slice_t bvt_do_schedule(s_time_t now)
             }
         } 
         
-        write_unlock_irqrestore(&tasklist_lock, t_flags); 
+        write_unlock(&tasklist_lock);
         
         CPU_SVT(cpu) -= 0xe0000000;
     }
@@ -591,43 +516,29 @@ static void bvt_dump_settings(void)
 
 static void bvt_dump_cpu_state(int i)
 {
-    unsigned long flags;
     struct list_head *list, *queue;
     int loop = 0;
     struct bvt_dom_info *d_inf;
     struct domain *d;
     
-    spin_lock_irqsave(&CPU_INFO(i)->run_lock, flags);
     printk("svt=0x%08lX ", CPU_SVT(i));
 
     queue = RUNQUEUE(i);
     printk("QUEUE rq %lx   n: %lx, p: %lx\n",  (unsigned long)queue,
-        (unsigned long) queue->next, (unsigned long) queue->prev);
+           (unsigned long) queue->next, (unsigned long) queue->prev);
 
     list_for_each ( list, queue )
     {
         d_inf = list_entry(list, struct bvt_dom_info, run_list);
         d = d_inf->domain;
         printk("%3d: %u has=%c ", loop++, d->domain,
-              test_bit(DF_RUNNING, &d->flags) ? 'T':'F');
+               test_bit(DF_RUNNING, &d->flags) ? 'T':'F');
         bvt_dump_runq_el(d);
         printk("c=0x%X%08X\n", (u32)(d->cpu_time>>32), (u32)d->cpu_time);
         printk("         l: %lx n: %lx  p: %lx\n",
-            (unsigned long)list, (unsigned long)list->next,
-            (unsigned long)list->prev);
+               (unsigned long)list, (unsigned long)list->next,
+               (unsigned long)list->prev);
     }
-    spin_unlock_irqrestore(&CPU_INFO(i)->run_lock, flags);        
-}
-
-/* We use cache to create the bvt_dom_infos 
-   this functions makes sure that the run_list
-   is initialised properly.
-   Call to __task_on_runqueue needs to return false */
-static void cache_constructor(void *arg1, xmem_cache_t *arg2, unsigned long arg3)
-{
-    struct bvt_dom_info *dom_inf = (struct bvt_dom_info*)arg1;
-    dom_inf->run_list.next = NULL;
-    dom_inf->run_list.prev = NULL;
 }
 
 /* Initialise the data structures. */
@@ -646,15 +557,12 @@ int bvt_init_scheduler()
         }
 
         INIT_LIST_HEAD(RUNQUEUE(i));
-        spin_lock_init(&CPU_INFO(i)->run_lock);
         
         CPU_SVT(i) = 0; /* XXX do I really need to do this? */
     }
 
-    dom_info_cache = xmem_cache_create("BVT dom info",
-                                       sizeof(struct bvt_dom_info),
-                                       0, 0, cache_constructor, NULL);
-
+    dom_info_cache = xmem_cache_create(
+        "BVT dom info", sizeof(struct bvt_dom_info), 0, 0, NULL, NULL);
     if ( dom_info_cache == NULL )
     {
         printk("BVT: Failed to allocate domain info SLAB cache");
@@ -664,8 +572,6 @@ int bvt_init_scheduler()
     return 0;
 }
 
-
-
 struct scheduler sched_bvt_def = {
     .name     = "Borrowed Virtual Time",
     .opt_name = "bvt",
@@ -676,7 +582,6 @@ struct scheduler sched_bvt_def = {
     .alloc_task     = bvt_alloc_task,
     .add_task       = bvt_add_task,
     .free_task      = bvt_free_task,
-    .do_block       = bvt_do_block,
     .do_schedule    = bvt_do_schedule,
     .control        = bvt_ctl,
     .adjdom         = bvt_adjdom,
@@ -685,4 +590,3 @@ struct scheduler sched_bvt_def = {
     .sleep          = bvt_sleep,
     .wake           = bvt_wake,
 };
-
index a986ee06a1f48cc2ad02e77f794402a14fb23963..31be94be359079d806b8f06f94898a4054fec9a7 100644 (file)
@@ -67,16 +67,19 @@ static void fallback_timer_fn(unsigned long unused);
 /* This is global for now so that private implementations can reach it */
 schedule_data_t schedule_data[NR_CPUS];
 
-/*
- * TODO: It would be nice if the schedulers array could get populated
- * automagically without having to hack the code in here.
- */
-extern struct scheduler sched_bvt_def, sched_fbvt_def, sched_rrobin_def, sched_atropos_def;
-static struct scheduler *schedulers[] = { &sched_bvt_def,
-                                                             &sched_fbvt_def,
-                                          &sched_rrobin_def,
-                                          &sched_atropos_def,
-                                          NULL};
+extern struct scheduler sched_bvt_def;
+extern struct scheduler sched_fbvt_def;
+extern struct scheduler sched_rrobin_def;
+extern struct scheduler sched_atropos_def;
+static struct scheduler *schedulers[] = { 
+    &sched_bvt_def,
+#ifdef BROKEN_SCHEDULERS
+    &sched_fbvt_def,
+    &sched_rrobin_def,
+    &sched_atropos_def,
+#endif
+    NULL
+};
 
 /* Operations for the current scheduler. */
 static struct scheduler ops;
@@ -155,21 +158,20 @@ void sched_rem_domain(struct domain *d)
 
 void init_idle_task(void)
 {
-    struct domain *d = current;
-
-    if ( SCHED_OP(init_idle_task, d) < 0)
-        panic("Failed to initialise idle task for processor %d",d->processor);
+    if ( SCHED_OP(init_idle_task, current) < 0 )
+        BUG();
 }
 
 void domain_sleep(struct domain *d)
 {
     unsigned long flags;
 
-    /* sleep and wake protected by domain's sleep_lock */
-    spin_lock_irqsave(&d->sleep_lock, flags);
+    spin_lock_irqsave(&schedule_data[d->processor].schedule_lock, flags);
+
     if ( likely(!domain_runnable(d)) )
         SCHED_OP(sleep, d);
-    spin_unlock_irqrestore(&d->sleep_lock, flags);
+
+    spin_unlock_irqrestore(&schedule_data[d->processor].schedule_lock, flags);
  
     /* Synchronous. */
     while ( test_bit(DF_RUNNING, &d->flags) && !domain_runnable(d) )
@@ -181,10 +183,10 @@ void domain_sleep(struct domain *d)
 
 void domain_wake(struct domain *d)
 {
-    unsigned long       flags;
+    unsigned long flags;
+
+    spin_lock_irqsave(&schedule_data[d->processor].schedule_lock, flags);
 
-    spin_lock_irqsave(&d->sleep_lock, flags);
-    
     if ( likely(domain_runnable(d)) )
     {
         TRACE_2D(TRC_SCHED_WAKE, d->domain, d);
@@ -196,7 +198,7 @@ void domain_wake(struct domain *d)
     
     clear_bit(DF_MIGRATED, &d->flags);
     
-    spin_unlock_irqrestore(&d->sleep_lock, flags);
+    spin_unlock_irqrestore(&schedule_data[d->processor].schedule_lock, flags);
 }
 
 /* Block the currently-executing domain until a pertinent event occurs. */
@@ -218,7 +220,6 @@ static long do_yield(void)
     return 0;
 }
 
-
 /*
  * Demultiplex scheduler-related hypercalls.
  */
@@ -292,24 +293,25 @@ long sched_ctl(struct sched_ctl_cmd *cmd)
 /* Adjust scheduling parameter for a given domain. */
 long sched_adjdom(struct sched_adjdom_cmd *cmd)
 {
-    struct domain *p;    
-    
+    struct domain *d;
+
     if ( cmd->sched_id != ops.sched_id )
         return -EINVAL;
 
     if ( cmd->direction != SCHED_INFO_PUT && cmd->direction != SCHED_INFO_GET )
         return -EINVAL;
 
-    p = find_domain_by_id(cmd->domain);
-
-    if( p == NULL )
+    d = find_domain_by_id(cmd->domain);
+    if ( d == NULL )
         return -ESRCH;
 
-    TRACE_1D(TRC_SCHED_ADJDOM, p->domain);
+    TRACE_1D(TRC_SCHED_ADJDOM, d->domain);
 
-    SCHED_OP(adjdom, p, cmd);
+    spin_lock_irq(&schedule_data[d->processor].schedule_lock);
+    SCHED_OP(adjdom, d, cmd);
+    spin_unlock_irq(&schedule_data[d->processor].schedule_lock);
 
-    put_domain(p); 
+    put_domain(d);
     return 0;
 }
 
@@ -335,7 +337,6 @@ void __enter_scheduler(void)
     rem_ac_timer(&schedule_data[cpu].s_timer);
     
     ASSERT(!in_irq());
-    // TODO - move to specific scheduler ASSERT(__task_on_runqueue(prev));
 
     if ( test_bit(DF_BLOCKED, &prev->flags) )
     {
@@ -362,6 +363,9 @@ void __enter_scheduler(void)
     schedule_data[cpu].s_timer.expires  = now + r_time;
     add_ac_timer(&schedule_data[cpu].s_timer);
 
+    /* Must be protected by the schedule_lock! */
+    set_bit(DF_RUNNING, &next->flags);
+
     spin_unlock_irq(&schedule_data[cpu].schedule_lock);
 
     /* Ensure that the domain has an up-to-date time base. */
@@ -405,7 +409,6 @@ void __enter_scheduler(void)
      * without warning). 
      */
     clear_bit(DF_RUNNING, &prev->flags);
-    set_bit(DF_RUNNING, &next->flags);
 
     /* Mark a timer event for the newly-scheduled domain. */
     if ( !is_idle_task(next) )
@@ -549,15 +552,23 @@ void dump_runq(u_char key, void *dev_id, struct pt_regs *regs)
 {
     s_time_t      now = NOW();
     int           i;
+    unsigned long flags;
+
+    local_irq_save(flags);
 
     printk("Scheduler: %s (%s)\n", ops.name, ops.opt_name);
     SCHED_OP(dump_settings);
     printk("NOW=0x%08X%08X\n",  (u32)(now>>32), (u32)now); 
+
     for ( i = 0; i < smp_num_cpus; i++ )
     {
+        spin_lock(&schedule_data[i].schedule_lock);
         printk("CPU[%02d] ", i);
         SCHED_OP(dump_cpu_state,i);
+        spin_unlock(&schedule_data[i].schedule_lock);
     }
+
+    local_irq_restore(flags);
 }
 
 #if defined(WAKE_HISTO) || defined(BLOCKTIME_HISTO)
index 99368a7a12d3f8b5c1a3ae760b14caf32c29b899..10fb93bac078641df194182f213f8183db308ca2 100644 (file)
@@ -97,7 +97,6 @@ struct domain
 
     /* Scheduling. */
     int              shutdown_code; /* code value from OS (if DF_SHUTDOWN). */
-    spinlock_t       sleep_lock;    /* wake/sleep lock                      */
     s_time_t         lastschd;      /* time this domain was last scheduled */
     s_time_t         lastdeschd;    /* time this domain was last descheduled */
     s_time_t         cpu_time;      /* total CPU time received till now */